#ifndef  __POLL_SVR_H__
#define __POLL_SVR_H__

#include <iostream>
#include <string>
#include <poll.h>
#include <sys/time.h> 
#include "Log.hpp"
#include "Sock.hpp"

#define BITS 8
#define NUM (sizeof(fd_set)*BITS)
#define FD_NONE -1

using namespace std;
class pollServer
{
public:
    static const int nfds = 100;
public:
    pollServer(const uint16_t &port = 8080):_port(port),_nfds(nfds)
    {
        _listensock = Sock::Socket();
        Sock::Bind(_listensock,_port);
        Sock::Listen(_listensock);
        logMessage(DEBUG,"create base socket sucess");

        _fds = new struct pollfd[_nfds];
        for(int i = 0;i<_nfds;i++) {
            _fds[i].fd = FD_NONE;
            _fds[i].events = _fds[i].revents = 0;
        }
        _fds[0].fd = _listensock;
        _fds[0].events = POLLIN;

        _timeout = 1000;
    }

    void Start()
    {
        while (true)
        {
            int n = poll(_fds,_nfds,_timeout);//阻塞等待
            switch (n)
            {
            case 0:
                logMessage(DEBUG,"time out...");
                break;
            case -1:
                logMessage(DEBUG,"select error : %d : %s",errno,strerror(errno));
                break;
            default:
                HandlerEvent();
                break;
            }
        }
        
    }

    ~pollServer()
    {
        if(_listensock >=0) close(_listensock);
        if(_fds) delete [] _fds;
    }
private:
    void HandlerEvent()//fd_set 是一个集合
    {
        for(int i = 0;i<_nfds;i++)
        {
            if(_fds[i].fd == FD_NONE) continue;
            if(_fds[i].revents & POLLIN)
            {
                if(_fds[i].fd == _listensock)
                {
                    //读事件就绪：连接时间到来，accept
                    Accepter();
                }
                else
                {
                    Recver(i);
                }
            }
        }
    }
    void Recver(int pos)
    {
        //读事件就绪：IINPUT事件到来,recv,read
        logMessage(DEBUG,"message int,get IO event: %d",_fds[pos]);
        char buffer[1024];
        int n = recv(_fds[pos].fd,buffer,sizeof(buffer)-1,0);
        if(n > 0)
        {
            buffer[n] = 0;
            logMessage(DEBUG,"client[%d]# %s",_fds[pos].fd,buffer);
        }
        else if(n ==0)
        {
            logMessage(DEBUG,"client[%d] quit,me to..",_fds[pos].fd);
            close(_fds[pos].fd);
            _fds[pos].fd = FD_NONE;
            _fds[pos].events = 0;
        }else
        {
            logMessage(WARNING, "%d sock recv error, %d : %s", _fds[pos].fd, errno, strerror(errno));
            close(_fds[pos].fd);
            _fds[pos].fd = FD_NONE;
            _fds[pos].events = 0;

        }
    }
    void Accepter()
    {
        string clientip;
        uint16_t clientport = 0;
        
        int sock = Sock::Accept(_listensock,&clientip,&clientport);
        if(sock < 0)
        {
            logMessage(WARNING,"accept error");
            return;
        }
        logMessage(DEBUG,"get a new line sucess : [%s:%d] : %d",clientip.c_str(),clientport,sock);
        int pos = 1;
        for(;pos < _nfds;pos++)
        {
            if(_fds[pos].fd == FD_NONE) break;
        }
        if(pos == NUM)
        {
            logMessage(WARNING,"%s:%d","poll server already full close: %d",sock);
            close(sock);
        }
        else{
            _fds[pos].fd = sock;
            _fds[pos].events = POLLIN;
        }    
    }
    
    void DebugPrint()
    {
        cout << "_fd_arry[]: ";
        for(int i =0;i<NUM;i++)
        {
            if(_fds[i].fd == FD_NONE) continue;
            cout<< _fds[i].fd<<" ";
        }
        cout<<endl;
    }
private:
    uint16_t _port;
    int _listensock;
    struct pollfd *_fds;
    int _nfds;
    int _timeout;
};
#endif